home *** CD-ROM | disk | FTP | other *** search
- Subject: v19i095: Cnews production release, Part18/19
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: utzoo!henry
- Posting-number: Volume 19, Issue 95
- Archive-name: cnews2/part18
-
- : ---CUT HERE---
- echo 'rna/header.c':
- sed 's/^X//' >'rna/header.c' <<'!'
- X/*
- X * extract/output headers
- X */
- X
- X#include "defs.h"
- X
- X#if AUSAM
- Xextern struct pwent pe;
- X#else
- Xextern struct passwd *pp;
- X#endif
- Xextern char systemid[];
- Xextern long now;
- X
- Xchar tzone[] = TIMEZONE;
- Xchar hform[] = "%s: %s\n";
- X
- X/* Mandatory Headers */
- Xchar t_relayversion[] = "Relay-Version";
- Xchar t_postversion[] = "Posting-Version";
- Xchar t_from[] = "From";
- Xchar t_date[] = "Date";
- Xchar t_newsgroups[] = "Newsgroups";
- Xchar t_subject[] = "Subject";
- Xchar t_messageid[] = "Message-ID";
- Xchar t_path[] = "Path";
- X
- X/* Optional Headers */
- Xchar t_replyto[] = "Reply-To";
- Xchar t_sender[] = "Sender";
- Xchar t_followupto[] = "Followup-To";
- Xchar t_datereceived[] = "Date-Received";
- Xchar t_expires[] = "Expires";
- Xchar t_references[] = "References";
- Xchar t_control[] = "Control";
- Xchar t_distribution[] = "Distribution";
- Xchar t_organization[] = "Organization";
- Xchar t_lines[] = "Lines";
- X
- Xtypedef enum ft
- X{
- X f_control, f_date, f_datereceived, f_distribution,
- X f_expires, f_followupto, f_from, f_lines, f_messageid,
- X f_newsgroups, f_organization, f_path, f_postversion,
- X f_references, f_relayversion, f_replyto, f_sender,
- X f_subject
- X}
- X
- X
- Xftype;
- X
- Xtypedef struct field {
- X char *f_name;
- X ftype f_type;
- X} field;
- X
- Xstatic field fields[] =
- X{
- X { t_control, f_control },
- X { t_date, f_date },
- X { t_datereceived, f_datereceived },
- X { t_distribution, f_distribution },
- X { t_expires, f_expires },
- X { t_followupto, f_followupto },
- X { t_from, f_from },
- X { t_lines, f_lines },
- X { t_messageid, f_messageid },
- X { t_newsgroups, f_newsgroups },
- X { t_organization, f_organization },
- X { t_path, f_path },
- X { t_postversion, f_postversion },
- X { t_references, f_references },
- X { t_relayversion, f_relayversion },
- X { t_replyto, f_replyto },
- X { t_sender, f_sender },
- X { t_subject, f_subject }
- X};
- X
- X
- Xchar *weekdays[7] =
- X{
- X "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- X};
- X
- X
- Xchar *months[12] =
- X{
- X "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- X "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- X};
- X
- X
- Xstatic
- Xfieldcmp(a, b)
- Xfield *a, *b;
- X{
- X return CMP(a->f_name, b->f_name);
- X}
- X
- X
- X/*
- X * extract headers from file,
- X * position file to start of body
- X */
- Xgethead(f, hp)
- XFILE *f;
- Xheader *hp;
- X{
- X register char *colon, *space, *s;
- X register field *fp;
- X field af;
- X char buf[BUFLEN*2];
- X
- X char *hfgets();
- X
- X memset((char *) hp, 0, sizeof(header));
- X while (hfgets(buf, sizeof(buf), f)) {
- X if (buf[0] == '\n')
- X return;
- X if (isupper(buf[0]) && (colon = strchr(buf, ':')) && (space =
- X strchr(buf, ' ')) && (colon + 1 == space)) {
- X *colon = '\0';
- X af.f_name = buf;
- X fp = (field * ) bsearch((char *) & af, (char *) fields,
- X sizeof(fields) / sizeof(fields[0]), sizeof(fields[0]),
- X fieldcmp);
- X *colon = ':';
- X } else
- X fp = NIL(field);
- X if (!fp)
- X if (hp->h_others)
- X hp->h_others = catstr(hp->h_others, buf);
- X else
- X hp->h_others = newstr(buf);
- X else
- X {
- X if (colon = strchr(space + 1, '\n'))
- X *colon = '\0';
- X s = newstr(space + 1);
- X switch (fp->f_type) {
- X case f_control:
- X hp->h_control = s;
- X break;
- X case f_date:
- X hp->h_date = s;
- X break;
- X case f_datereceived:
- X hp->h_datereceived = s;
- X break;
- X case f_distribution:
- X hp->h_distribution = s;
- X break;
- X case f_expires:
- X hp->h_expires = s;
- X break;
- X case f_followupto:
- X hp->h_followupto = s;
- X break;
- X case f_from:
- X hp->h_from = s;
- X break;
- X case f_lines:
- X hp->h_lines = s;
- X break;
- X case f_messageid:
- X hp->h_messageid = s;
- X break;
- X case f_newsgroups:
- X hp->h_newsgroups = s;
- X break;
- X case f_organization:
- X hp->h_organisation = s;
- X break;
- X case f_path:
- X hp->h_path = s;
- X break;
- X case f_postversion:
- X hp->h_postversion = s;
- X break;
- X case f_references:
- X hp->h_references = s;
- X break;
- X case f_relayversion:
- X hp->h_relayversion = s;
- X break;
- X case f_replyto:
- X hp->h_replyto = s;
- X break;
- X case f_sender:
- X hp->h_sender = s;
- X break;
- X case f_subject:
- X hp->h_subject = s;
- X break;
- X }
- X }
- X }
- X}
- X
- X
- X/*
- X * put headers to file
- X */
- Xputhead(hp, f, com)
- Xheader *hp;
- XFILE *f;
- Xpheadcom com;
- X{
- X register char *s;
- X char *getunique();
- X extern char *getenv();
- X
- X if (hp->h_relayversion && com == printing)
- X (void) fprintf(f, hform, t_relayversion, hp->h_relayversion);
- X else if (com != printing)
- X (void) fprintf(f, "%s: version %s; site %s.%s\n", t_relayversion, NEWSVERSION,
- X systemid, MYDOMAIN);
- X
- X if (hp->h_postversion)
- X (void) fprintf(f, hform, t_postversion, hp->h_postversion);
- X else if (com == making)
- X (void) fprintf(f, "%s: version %s; site %s.%s\n", t_postversion, NEWSVERSION,
- X systemid, MYDOMAIN);
- X
- X
- X if (hp->h_from)
- X (void) fprintf(f, hform, t_from, hp->h_from);
- X else if(com == making) {
- X if(s = getenv("NAME"))
- X (void) fprintf(f, "%s: %s@%s.%s (%s)\n", t_from,
- X#if AUSAM
- X pe.pw_strings[LNAME],
- X#else
- X pp->pw_name,
- X#endif
- X systemid, MYDOMAIN, s);
- X else
- X (void) fprintf(f,
- X#if AUSAM
- X "%s: %s@%s.%s (%s %s)\n",
- X#else
- X "%s: %s@%s.%s\n",
- X#endif
- X t_from,
- X#if AUSAM
- X pe.pw_strings[LNAME],
- X#else
- X pp->pw_name,
- X#endif
- X systemid, MYDOMAIN
- X#if AUSAM
- X ,
- X pe.pw_strings[FIRSTNAME],
- X pe.pw_strings[LASTNAME]
- X#endif
- X );
- X }
- X
- X if (hp->h_date)
- X (void) fprintf(f, hform, t_date, hp->h_date);
- X else if (com == making)
- X (void) fprintf(f, hform, t_date, ttoa(now));
- X
- X if (hp->h_newsgroups)
- X (void) fprintf(f, hform, t_newsgroups, hp->h_newsgroups);
- X else if (com == making)
- X (void) fprintf(f, hform, t_newsgroups, DFLTGRP);
- X
- X if (hp->h_subject)
- X (void) fprintf(f, hform, t_subject, hp->h_subject);
- X else if (com == making)
- X error("No subject field.");
- X
- X if (hp->h_messageid)
- X (void) fprintf(f, hform, t_messageid, hp->h_messageid);
- X else if (com == making)
- X error("No messageid.");
- X
- X if (hp->h_path && com == passing)
- X (void) fprintf(f, "%s: %s!%s\n", t_path, systemid, hp->h_path);
- X else if (hp->h_path)
- X (void) fprintf(f, hform, t_path, hp->h_path);
- X else if(com == making)
- X (void) fprintf(f, "%s: %s!%s\n", t_path, systemid,
- X#if AUSAM
- X pe.pw_strings[LNAME]
- X#else
- X pp->pw_name
- X#endif
- X );
- X
- X /* optional */
- X
- X if (hp->h_replyto)
- X (void) fprintf(f, hform, t_replyto, hp->h_replyto);
- X
- X if (hp->h_sender)
- X (void) fprintf(f, hform, t_sender, hp->h_sender);
- X
- X if (hp->h_followupto)
- X (void) fprintf(f, hform, t_followupto, hp->h_followupto);
- X
- X if (hp->h_datereceived && com == printing)
- X (void) fprintf(f, hform, t_datereceived, hp->h_datereceived);
- X else if (com != printing)
- X (void) fprintf(f, hform, t_datereceived, ttoa(now));
- X
- X if (hp->h_expires)
- X (void) fprintf(f, hform, t_expires, hp->h_expires);
- X
- X if (hp->h_references)
- X (void) fprintf(f, hform, t_references, hp->h_references);
- X
- X if (hp->h_control)
- X (void) fprintf(f, hform, t_control, hp->h_control);
- X
- X if (hp->h_distribution)
- X (void) fprintf(f, hform, t_distribution, hp->h_distribution);
- X
- X if (hp->h_organisation)
- X (void) fprintf(f, hform, t_organization, hp->h_organisation);
- X else if (com == making)
- X (void) fprintf(f, hform, t_organization, (s = getenv("ORGANIZATION")) ?
- X s : MYORG);
- X
- X if (hp->h_lines)
- X (void) fprintf(f, hform, t_lines, hp->h_lines);
- X
- X if (hp->h_others)
- X fputs(hp->h_others, f);
- X}
- X
- X
- X/*
- X * free all strings allocated to header
- X */
- Xfreehead(hp)
- Xregister header *hp;
- X{
- X if (hp->h_relayversion)
- X free(hp->h_relayversion);
- X if (hp->h_postversion)
- X free(hp->h_postversion);
- X if (hp->h_from)
- X free(hp->h_from);
- X if (hp->h_date)
- X free(hp->h_date);
- X if (hp->h_newsgroups)
- X free(hp->h_newsgroups);
- X if (hp->h_subject)
- X free(hp->h_subject);
- X if (hp->h_messageid)
- X free(hp->h_messageid);
- X if (hp->h_path)
- X free(hp->h_path);
- X if (hp->h_replyto)
- X free(hp->h_replyto);
- X if (hp->h_sender)
- X free(hp->h_sender);
- X if (hp->h_followupto)
- X free(hp->h_followupto);
- X if (hp->h_datereceived)
- X free(hp->h_datereceived);
- X if (hp->h_expires)
- X free(hp->h_expires);
- X if (hp->h_references)
- X free(hp->h_references);
- X if (hp->h_control)
- X free(hp->h_control);
- X if (hp->h_distribution)
- X free(hp->h_distribution);
- X if (hp->h_organisation)
- X free(hp->h_organisation);
- X if (hp->h_lines)
- X free(hp->h_lines);
- X if (hp->h_others)
- X free(hp->h_others);
- X}
- X
- X
- X/*
- X * hfgets is like fgets, but deals with continuation lines.
- X * It also ensures that even if a line that is too long is
- X * received, the remainder of the line is thrown away
- X * instead of treated like a second line.
- X */
- Xchar *
- Xhfgets(buf, len, fp)
- Xchar *buf;
- Xint len;
- XFILE *fp;
- X{
- X register int c;
- X register char *cp, *tp;
- X
- X if ((cp = fgets(buf, len, fp)) == NIL(char))
- X return NIL(char);
- X
- X if (*cp == '\n')
- X return cp;
- X
- X tp = cp + strlen(cp);
- X if (tp[-1] != '\n') {
- X /* Line too long - part read didn't fit into a newline */
- X while ((c = getc(fp)) != '\n' && c != EOF)
- X ;
- X } else
- X *--tp = '\0'; /* clobber newline */
- X
- X while ((c = getc(fp)) == ' ' || c == '\t') {
- X /* Continuation line. */
- X while ((c = getc(fp)) == ' ' || c == '\t')
- X ;
- X if (tp - cp < len) {
- X *tp++ = ' ';
- X *tp++ = c;
- X }
- X while ((c = getc(fp)) != '\n' && c != EOF)
- X if (tp - cp < len)
- X *tp++ = c;
- X }
- X *tp++ = '\n';
- X *tp++ = '\0';
- X if (c != EOF)
- X ungetc(c, fp); /* push back first char of next header */
- X return cp;
- X}
- X
- X
- X/*
- X * time to ascii
- X * leave time in static var
- X */
- Xchar *
- Xttoa(t)
- Xlong t;
- X{
- X static char buf[40];
- X struct tm *tp;
- X extern struct tm *localtime();
- X
- X tp = localtime(&t);
- X sprintf(buf, "%s, %d %s %d %02d:%02d:%02d %s", weekdays[tp->tm_wday],
- X tp->tm_mday, months[tp->tm_mon], tp->tm_year, tp->tm_hour, tp->tm_min,
- X tp->tm_sec, tzone);
- X return buf;
- X
- X}
- X
- X
- X/*
- X * ascii to time
- X * return 0L on error
- X */
- Xlong
- Xatot(s)
- Xchar *s;
- X{
- X char *argv[4];
- X int day, year, hour, min, sec;
- X char month[10], sday[10], stime[10], syear[10];
- X extern long maketime();
- X
- X if (sscanf(s, "%*s %d %*[ -] %9[^ -] %*[ -] %d %2d:%2d:%2d", &day, month,
- X &year, &hour, &min, &sec) != 6)
- X return 0L;
- X sprintf(sday, "%d", day);
- X sprintf(stime, "%d:%d:%d", hour, min, sec);
- X sprintf(syear, "%d", 1900 + year);
- X argv[0] = sday;
- X argv[1] = month;
- X argv[2] = stime;
- X argv[3] = syear;
- X return maketime(4, argv, STIMES);
- X}
- X
- X
- !
- echo 'rna/history.c':
- sed 's/^X//' >'rna/history.c' <<'!'
- X/*
- X * History file
- X * each line contains a message-id, install or expire time
- X * names of linked files
- X */
- X
- X#include "defs.h"
- X
- Xstatic char histname[] = HISTORY;
- Xstatic char *histid; /* messageid to save */
- Xstatic char *histline; /* list of linked files */
- Xstatic long etime; /* expire time */
- X
- Xtypedef enum stypes {
- X chk, delete } stype;
- X
- X/*
- X * do things with history file
- X * chk - see if id present
- X * delete - delete article with id
- X */
- Xstatic bool
- Xsearchhist(id, type)
- Xchar *id;
- Xstype type;
- X{
- X register FILE *f;
- X register char *s, *name;
- X register bool found;
- X char buf[BUFSIZ * 2];
- X
- X extern char *newsdir;
- X
- X f = fopenl(histname);
- X
- X found = false;
- X while (fgets(buf, sizeof(buf), f)) {
- X if (s = strchr(buf, ' '))
- X *s = '\0';
- X else
- X error("Bad format: %s", histname);
- X if (CMP(buf, id) == 0) {
- X found = true;
- X break;
- X }
- X }
- X if (found && type == delete) {
- X if ((name = strchr(s + 1, ' ')) == NIL(char))
- X error("Bad format: %s", histname);
- X name++;
- X while (name && (s = strpbrk(name, " \n"))) {
- X *s = '\0';
- X name = newstr3(newsdir, "/", name);
- X remove(name);
- X free(name);
- X name = s + 1;
- X }
- X }
- X fclose(f);
- X#if !AUSAM
- X unlock(histname);
- X#endif
- X return found;
- X}
- X
- X
- X/*
- X * delete files given id
- X */
- Xbool
- Xcancel(id)
- Xchar *id;
- X{
- X bool searchhist();
- X
- X return searchhist(id, delete);
- X}
- X
- X
- X/*
- X * check if article has been recieved
- X */
- Xbool
- Xchkhist(id)
- Xchar *id;
- X{
- X bool searchhist();
- X
- X return searchhist(id, chk);
- X}
- X
- X
- X/*
- X * scan history, clearing uflag list entry if id not seen
- X */
- Xscanhist(ulist, usize)
- Xchar **ulist;
- Xint usize;
- X{
- X register FILE *f;
- X register char *s, **found;
- X register int i;
- X char *key[1];
- X char buf[BUFSIZ * 2];
- X bool * seen;
- X
- X extern char *newsdir;
- X
- X seen = (bool * ) myalloc((int) sizeof(bool) * usize);
- X memset((char *)seen, 0, (int) sizeof(bool) * usize);
- X
- X f = fopenf(histname, "r");
- X while (fgets(buf, sizeof(buf), f)) {
- X if (s = strchr(buf, ' '))
- X *s = '\0';
- X else
- X error("Bad format: %s", histname);
- X key[0] = buf;
- X found = (char **) bsearch((char *) key, (char *) ulist, (unsigned) usize,
- X sizeof(char *), strpcmp);
- X if (found)
- X seen[found - ulist] = true;
- X }
- X fclose(f);
- X
- X for (i = 0; i < usize; i++)
- X if (!seen[i]) {
- X free(ulist[i]);
- X ulist[i] = NIL(char);
- X }
- X free((char *)seen);
- X}
- X
- X
- X/*
- X * open hist file, write id and time
- X */
- Xopenhist(hp)
- Xheader *hp;
- X{
- X
- X histid = newstr(hp->h_messageid);
- X if (hp->h_expires)
- X etime = atot(hp->h_expires);
- X else
- X etime = 0L;
- X histline = NIL(char);
- X}
- X
- X
- X/*
- X * write name of file article resides into history file
- X */
- Xwritehist(fname)
- Xchar *fname;
- X{
- X histline = (histline ? catstr2(histline, " ", fname) : newstr(fname));
- X}
- X
- X
- X/*
- X * close history file
- X */
- Xclosehist()
- X{
- X register FILE *f;
- X extern long now;
- X
- X f = fopenl(histname);
- X fseek(f, 0L, 2);
- X (void) fprintf(f, "%s %s%ld %s\n", histid, etime ? "E" : "", etime ? etime :
- X now, histline);
- X fclose(f);
- X#if !AUSAM
- X unlock(histname);
- X#endif
- X free(histid);
- X free(histline);
- X}
- X
- X
- X/*
- X * remove a news item
- X * check owner first
- X */
- Xstatic
- Xremove(fname)
- Xchar *fname;
- X{
- X header h;
- X FILE * f;
- X register char *s, *mname;
- X
- X#if AUSAM
- X extern struct pwent pe;
- X#else
- X extern struct passwd *pp;
- X#endif
- X extern char systemid[];
- X extern bool su;
- X extern bool pflag;
- X
- X if (!su && !pflag) {
- X f = fopenf(fname, "r");
- X gethead(f, &h);
- X fclose(f);
- X if (s = strchr(h.h_from, ' '))
- X *s = '\0';
- X mname = newstr5(
- X#if AUSAM
- X pe.pw_strings[LNAME],
- X#else
- X pp->pw_name,
- X#endif
- X "@", systemid, ".", MYDOMAIN);
- X if (CMP(mname, h.h_from) != 0)
- X error("Can't cancel articles you didn't write.");
- X free(mname);
- X }
- X if (unlink(fname) != 0)
- X error("Couldn't unlink %s", fname);
- X
- X}
- !
- echo 'rna/lib/bsearch.c':
- sed 's/^X//' >'rna/lib/bsearch.c' <<'!'
- X/*LINTLIBRARY*/
- X/*
- X * Binary search algorithm, generalized from Knuth (6.2.1) Algorithm B.
- X *
- X * Written by J. S. Rugaber; rewritten by L. Rosler, Dept. 45175, August, 1981.
- X */
- X
- Xtypedef char *POINTER;
- X
- XPOINTER
- Xbsearch(key, base, nel, width, compar)
- XPOINTER key; /* Key to be located */
- XPOINTER base; /* Beginning of table */
- Xunsigned nel; /* Number of elements in the table */
- Xunsigned width; /* Width of an element (bytes) */
- Xint (*compar)(); /* Comparison function */
- X{
- X int two_width = width + width;
- X POINTER last = base + width * (nel - 1); /* Last element in table */
- X
- X while (last >= base) {
- X
- X register POINTER p = base + width * ((last - base)/two_width);
- X register int res = (*compar)(key, p);
- X
- X if (res == 0)
- X return (p); /* Key found */
- X if (res < 0)
- X last = p - width;
- X else
- X base = p + width;
- X }
- X return ((POINTER) 0); /* Key not found */
- X}
- !
- echo 'rna/lib/itoa.c':
- sed 's/^X//' >'rna/lib/itoa.c' <<'!'
- Xchar *
- Xitoa(i)
- Xint i;
- X{
- X static char buf[30];
- X
- X sprintf(buf, "%d", i);
- X return buf;
- X}
- !
- echo 'rna/lib/makefile':
- sed 's/^X//' >'rna/lib/makefile' <<'!'
- X# makefile for Australian readnews library
- XRANLIB=ranlib
- X# workaround for System V make bug
- XSHELL = /bin/sh
- X
- Xlib.a: bsearch.o itoa.o memset.o strpbrk.o
- X ar rv $@ bsearch.o itoa.o memset.o strpbrk.o
- X $(RANLIB) $@
- Xclean:
- X rm -f *.o *.a
- !
- echo 'rna/lib/memset.c':
- sed 's/^X//' >'rna/lib/memset.c' <<'!'
- X/*LINTLIBRARY*/
- X/*
- X * Set an array of n chars starting at sp to the character c.
- X * Return sp.
- X */
- Xchar *
- Xmemset(sp, c, n)
- Xregister char *sp, c;
- Xregister int n;
- X{
- X register char *sp0 = sp;
- X
- X while (--n >= 0)
- X *sp++ = c;
- X return (sp0);
- X}
- !
- echo 'rna/lib/strpbrk.c':
- sed 's/^X//' >'rna/lib/strpbrk.c' <<'!'
- X/*
- X * Return ptr to first occurance of any character from `brkset'
- X * in the character string `string'; NULL if none exists.
- X */
- X
- X#define NULL (char *) 0
- X
- Xchar *
- Xstrpbrk(string, brkset)
- Xregister char *string, *brkset;
- X{
- X register char *p;
- X
- X do {
- X for(p=brkset; *p != '\0' && *p != *string; ++p)
- X ;
- X if(*p != '\0')
- X return(string);
- X }
- X while(*string++);
- X return(NULL);
- X}
- !
- echo 'rna/COVER.pd':
- sed 's/^X//' >'rna/COVER.pd' <<'!'
- XFrom decvax!mulga!michaelr:elecvax Mon Jul 16 04:25:19 1984
- XFrom: decvax!mulga!michaelr:elecvax
- XReceived: by decvax.UUCP (4.12/1.0)
- X id AA25742; Mon, 16 Jul 84 03:56:35 edt
- XReceived: by mulga.OZ (4.3)
- X id AA06943; Mon, 16 Jul 84 14:19:46 EST
- XTo: decvax!utcsstat!geoff:mulga
- XSubject: Re: your news re-write
- X
- XYes, my news re-write is in the public domain.
- XI couldn't sell it if I wanted to, since it was developed under an
- Xeducational license.
- X
- XPlease distribute it freely as you wish.
- X
- XMichael Rourke
- XUniversity of New South Wales, Kensington, N.S.W. 2033 AUSTRALIA
- XPhone: +61 2 662 2781 Netaddr: {decvax,vax135,sfjec}!mulga!michaelr:elecvax
- X
- X
- !
- echo 'rna/makefile':
- sed 's/^X//' >'rna/makefile' <<'!'
- X# australian readnews makefile
- X# =()<NEWSARTS = @<NEWSARTS>@>()=
- XNEWSARTS = /usr/spool/news
- X# =()<NEWSBIN = @<NEWSBIN>@>()=
- XNEWSBIN = /usr/lib/newsbin
- X# =()<NEWSCTL = @<NEWSCTL>@>()=
- XNEWSCTL = /usr/lib/news
- X# workaround for System V make bug
- XSHELL = /bin/sh
- X
- XDEFINES=
- XCOPTS=-O
- XCFLAGS=$(COPTS) $(DEFINES)
- XINSTALL=:# install bigpdp
- XNFLAG =
- XLINT = lint -ha $(DEFINES)
- XI=/usr/include
- XC=/lib/libc.a
- XLIBS=lib/lib.a ../libcnews.a
- XBIN=/bin
- XBINDIR=$(BIN)
- X
- XCOMMANDS = postnews uurec readnews uusend expire postgroup
- XFILES = help
- XLCOMMANDS = postnews.lint uurec.lint readnews.lint uusend.lint expire.lint
- XPFILES = header.c postnews.c funcs.c active.c history.c maketime.c mtempnam.c
- XRFILES = header.c readnews.c funcs.c active.c newsrc.c history.c maketime.c
- XROFILES= header.o readnews.o funcs.o active.o newsrc.o history.o maketime.o
- XEFILES = expire.c funcs.c active.c
- X
- X.c.lint:
- X $(LINT) $< > $@
- X
- X.c:
- X $(CC) $(CFLAGS) $*.c $(NFLAG) -o $(@F)
- X $(INSTALL) $* bin 711 $@
- X
- X.sh:
- X $(INSTALL) -c $*.sh bin 755 $@
- X
- Xall: readnews checknews
- X : warning, defs.h may not be right for your system
- X
- Xreadnews: $(ROFILES) defs.h $(LIBS)
- X $(CC) $(CFLAGS) $(ROFILES) $(LIBS) -o $@
- X
- Xnewsinstall:
- X : "install all control files; don't overwrite any!"
- X -if test ! -r $(NEWSCTL)/news.help; then cp news.help $(NEWSCTL); fi
- X
- X# bininstall: make directories, install programs
- Xbininstall: install
- Xinstall: $(BINDIR)/readnews $(BINDIR)/checknews
- X$(BINDIR)/readnews: readnews
- X cp readnews $(BINDIR)
- X : "$(INSTALL) - readnews bin 711 $(BINDIR)/readnews $(BINDIR)/news"
- X$(BINDIR)/checknews: checknews
- X chmod +x checknews
- X cp checknews $(BINDIR)
- X
- Xdefs.h: at.h # $C
- X touch defs.h
- X
- Xlint: $(LCOMMANDS)
- X
- Xhelp: $(NEWSCTL)/help
- X$(NEWSCTL)/help: news.help
- X $(INSTALL) -c news.help news 644 $(NEWSCTL)/help
- X
- Xlib/lib.a:
- X : if you do not have ranlib, you will need to edit lib/makefile
- X (cd lib; make)
- X
- X$(ROFILES): defs.h
- X
- Xpostnews: $(BINDIR)/postnews
- X$(BINDIR)/postnews: $(PFILES) defs.h
- X $(CC) $(CFLAGS) $(PFILES) -o postnews
- X $(INSTALL) - postnews news 6711 $(BINDIR)/postnews
- X
- Xpostgroup: $(BINDIR)/postgroup
- X$(BINDIR)/postgroup: postgroup.sh
- X
- Xuurec: $(NEWSCTL)/uurec
- X$(NEWSCTL)/uurec: uurec.c defs.h
- X
- Xuusend: $(NEWSCTL)/uusend
- X$(NEWSCTL)/uusend: defs.h uusend.c
- X
- Xexpire: $(NEWSCTL)/expire
- X$(NEWSCTL)/expire: $(EFILES) defs.h
- X $(CC) $(CFLAGS) $(EFILES) $(NFLAG) -o expire
- X $(INSTALL) expire news 700 $(NEWSCTL)/expire
- X
- Xpostnews.lint: $(PFILES)
- X $(LINT) $(PFILES) > postnews.lint
- X
- Xreadnews.lint: $(RFILES)
- X $(LINT) $(RFILES) > readnews.lint
- X
- Xexpire.lint: $(EFILES)
- X $(LINT) $(EFILES) > expire.lint
- X
- Xuurec.lint: uurec.c defs.h
- Xuusend.lint: uusend.c defs.h
- X
- X.FINISH:
- X rm -s *.o
- Xclean:
- X rm -f *.o core a.out readnews
- X (cd lib ; make clean)
- !
- echo 'rna/maketime.c':
- sed 's/^X//' >'rna/maketime.c' <<'!'
- X/*
- X * long
- X * maketime(argc, argv, type)
- X *
- X * A standard routine to convert a future time (in English) to seconds.
- X * Arguments are order-independent (except for suffixes), and words
- X * may be shortened to a non-ambiguous abbreviation.
- X * As the time must be in the future, unspecified years, months and days default
- X * to the "next" year, month or day if necessary; otherwise the current
- X * month, day and hour are used.
- X *
- X * type is either TIMES in which days, times are recognised, or just DAYS.
- X *
- X * Tries hard to give meaningful messages, and make sure the user
- X * gets the time she/he wanted!
- X *
- X * Return is in seconds or 0 if error.
- X * Error messages to stderr.
- X *
- X * Michael Rourke (UNSW) Christmas 1982
- X *
- X * Syntax:
- X *
- X * timespec ::= { time | day | month | year } .
- X *
- X * time ::= [ hour [ ":" min [ ":" second ] ] ] [ timemodifier ] .
- X *
- X * timemodifier ::= "am" | "pm" | "noon" | "midday" | "midnight" | "now" .
- X *
- X * day ::= ( dayofweek [ "week" ] ) | number .
- X *
- X * dayofweek ::= "sunday" | "monday" | "tuesday" | "wednesday" |
- X * "thursday" | "friday" | "saturday" | "tomorrow" |
- X * "today" .
- X *
- X * month ::= "january" | "february" | "march" | "april" | "may" | "june" |
- X * "july" | "august" | "september" | "october" | "november" |
- X * "december" .
- X *
- X * year ::= "19" number .
- X *
- X */
- X
- X#include "defs.h"
- X
- X#define NOW -1
- X
- Xstatic timemod(), noonmid(), daymod(), weekday(), smonth();
- X
- Xstatic struct slist {
- X char *s_name;
- X int (*s_action)();
- X char s_val;
- X char s_type;
- X} slist[] =
- X{
- X { "am", timemod, 0, TIMES, },
- X { "pm", timemod, 12, TIMES, },
- X { "noon", noonmid, 12, TIMES, },
- X { "midday", noonmid, 12, TIMES, },
- X { "midnight", noonmid, 0, TIMES, },
- X { "now", noonmid, NOW, TIMES, },
- X { "week", daymod, 0, DAYS, },
- X { "sunday", weekday, 0, DAYS, },
- X { "monday", weekday, 1, DAYS, },
- X { "tuesday", weekday, 2, DAYS, },
- X { "wednesday", weekday, 3, DAYS, },
- X { "thursday", weekday, 4, DAYS, },
- X { "friday", weekday, 5, DAYS, },
- X { "saturday", weekday, 6, DAYS, },
- X { "tomorrow", weekday, 7, DAYS, },
- X { "today", weekday, 8, DAYS, },
- X { "january", smonth, 0, DAYS, },
- X { "february", smonth, 1, DAYS, },
- X { "march", smonth, 2, DAYS, },
- X { "april", smonth, 3, DAYS, },
- X { "may", smonth, 4, DAYS, },
- X { "june", smonth, 5, DAYS, },
- X { "july", smonth, 6, DAYS, },
- X { "august", smonth, 7, DAYS, },
- X { "september", smonth, 8, DAYS, },
- X { "october", smonth, 9, DAYS, },
- X { "november", smonth, 10, DAYS, },
- X { "december", smonth, 11, DAYS, },
- X { "", 0, 0, 0, }
- X};
- X
- X
- Xstatic char daysinmonth[12] =
- X{
- X 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
- X};
- X
- X
- Xstatic int hour, minute, second, day, year, dayofweek, month;
- Xstatic int settime, setday, setyear, setdayofweek, setmonth;
- Xstatic int setweek, err, setmod;
- Xstatic char *curarg;
- Xstatic struct tm *tim;
- Xstatic int gtype; /* global `type' arg */
- Xstatic short silent;
- X
- Xlong
- Xmaketime(argc, argv, type)
- Xint argc;
- Xchar **argv;
- Xint type;
- X{
- X struct tm *localtime();
- X long time(), construct(), now, then;
- X
- X if (type == STIMES)
- X type = TIMES, silent = 1;
- X else
- X silent = 0;
- X gtype = type;
- X now = time((long *) 0);
- X tim = localtime(&now);
- X
- X /*
- X * set defaults
- X */
- X hour = tim->tm_hour;
- X minute = tim->tm_min;
- X second = tim->tm_sec;
- X day = tim->tm_mday;
- X year = tim->tm_year + 1900;
- X dayofweek = tim->tm_wday;
- X month = tim->tm_mon;
- X
- X settime = setday = setyear = setdayofweek = setmonth = 0;
- X setweek = err = setmod = 0;
- X
- X while (argc--)
- X timearg(curarg = *argv++);
- X if (err)
- X return (long) 0;
- X
- X checktime();
- X if (err)
- X return (long) 0;
- X
- X then = construct();
- X /*
- X if(now > then)
- X {
- X error("Time specified has passed.");
- X return (long) 0;
- X }
- X*/
- X return then;
- X}
- X
- X
- Xstatic
- Xtimearg(s)
- Xchar *s;
- X{
- X lower(s);
- X if (isdigit(*s))
- X numbers(s);
- X else
- X words(s);
- X}
- X
- X
- Xstatic
- Xlower(s)
- Xregister char *s;
- X{
- X while (*s) {
- X *s = tolower(*s);
- X s++;
- X }
- X}
- X
- X
- Xstatic
- Xnumbers(s)
- Xregister char *s;
- X{
- X register int val;
- X
- X val = 0;
- X while (isdigit(*s))
- X val = val * 10 + *s++ - '0';
- X if (val > 1900)
- X if (setyear++)
- X reperror("year");
- X else
- X year = val;
- X else if (*s == '\0')
- X if (setday++)
- X reperror("day");
- X else
- X day = val;
- X else if (settime++)
- X reperror("time");
- X else
- X {
- X hour = val;
- X if (*s == ':') {
- X s++;
- X val = 0;
- X while (isdigit(*s))
- X val = val * 10 + *s++ - '0';
- X minute = val;
- X if (*s == ':') {
- X s++;
- X val = 0;
- X while (isdigit(*s))
- X val = val * 10 + *s++ - '0';
- X second = val;
- X } else
- X second = 0;
- X } else
- X minute = second = 0;
- X }
- X if (*s)
- X words(curarg = s);
- X}
- X
- X
- Xstatic
- Xreperror(s)
- Xchar *s;
- X{
- X error("Repeated %s argument: \"%s\"", s, curarg);
- X}
- X
- X
- X/* VARARGS1 */
- Xstatic
- Xerror(s, a1, a2, a3, a4)
- Xchar *s;
- Xint a1, a2, a3, a4;
- X{
- X err++;
- X if (silent)
- X return;
- X (void) fprintf(stderr, "Error in time specification: ");
- X (void) fprintf(stderr, s, a1, a2, a3, a4);
- X (void) fprintf(stderr, "\n");
- X}
- X
- X
- Xstatic
- Xwords(s)
- Xchar *s;
- X{
- X register struct slist *sp, *found;
- X register int size;
- X register char *wstart;
- X
- X sp = slist;
- X wstart = s;
- X size = 0;
- X while (*s && !isdigit(*s))
- X size++, s++;
- X found = (struct slist *) 0;
- X while (*(sp->s_name)) {
- X if (sp->s_type <= gtype && CMPN(sp->s_name, wstart, size) ==
- X 0)
- X if (!found) {
- X found = sp;
- X if (strlen(sp->s_name) == size)
- X break; /* otherwise an abbreviation */
- X }
- X else
- X {
- X error("Ambiguous abbreviation: \"%.*s\"", size,
- X wstart);
- X return;
- X }
- X sp++;
- X }
- X if (found)
- X (*(found->s_action))(found->s_val);
- X else
- X error("Unknown word: \"%.*s\"", size, wstart);
- X if (*s)
- X numbers(curarg = s);
- X}
- X
- X
- Xstatic
- Xtimemod(val)
- Xint val;
- X{
- X if (!settime)
- X error("Can only use \"am\" or \"pm\" after a time.");
- X else if (setmod++)
- X reperror("time modifier");
- X else if (hour < 12)
- X hour += val;
- X else if (hour > 12)
- X error("Can't use \"am\" or \"pm\" with 24 hour clock.");
- X else if (val == 0) /* am && hour == 12 */
- X hour = 0; /* 12am correction */
- X}
- X
- X
- Xstatic
- Xnoonmid(val)
- Xint val;
- X{
- X if (val < 0) /* NOW */ {
- X if (settime++)
- X reperror("time");
- X /* let defaults work */
- X } else if (setmod++) /* noon, midnight */
- X reperror("time modifier");
- X else
- X {
- X if (!settime)
- X settime++;
- X else if (hour != 12 || minute != 0 || second != 0)
- X error("Illegal time: %02d:%02d:%02d %s", hour, minute,
- X second, curarg);
- X hour = val;
- X minute = second = 0;
- X }
- X}
- X
- X
- Xstatic
- Xdaymod()
- X{
- X if (setweek++)
- X reperror("\b");
- X else if (!setdayofweek)
- X error("Can only use \"week\" after a weekday name.");
- X else
- X dayofweek += 7;
- X}
- X
- X
- Xstatic
- Xweekday(val)
- Xint val;
- X{
- X if (setday++)
- X reperror("day");
- X else
- X {
- X setdayofweek++;
- X if (val < 7) {
- X dayofweek = val - dayofweek; /* now a displacement */
- X if (dayofweek <= 0)
- X dayofweek += 7;
- X } else if (val == 7) /* tomorrow */
- X dayofweek = 1;
- X else /* today */
- X dayofweek = 0;
- X }
- X}
- X
- X
- Xstatic
- Xsmonth(val)
- Xint val;
- X{
- X if (setmonth++)
- X reperror("day of month");
- X else
- X month = val;
- X}
- X
- X
- Xstatic
- Xchecktime()
- X{
- X register int dim;
- X
- X if (gtype == DAYS && settime)
- X error("Times are not accepted.");
- X if (year < 1983 || year > 2038)
- X error("Year out of range.");
- X if (hour > 23 || minute > 59 || second > 59)
- X error("Illegal time: %02d:%02d:%02d", hour, minute, second);
- X if (!setdayofweek) {
- X dim = daysinmonth[month] + (month == 1 ? leapyear(year) : 0);
- X if (day > dim)
- X error("Month day out of range. (> %d)", dim);
- X }
- X if (setdayofweek && (setmonth || setyear))
- X error("Can't specify a weekday as well as a month or year.");
- X}
- X
- X
- Xstatic
- Xleapyear(y)
- Xint y;
- X{
- X return ((y % 4) == 0 && (y % 100) != 0) || (y % 400 == 0);
- X}
- X
- X
- Xstatic long
- Xconstruct()
- X{
- X register int i, days;
- X
- X adjust();
- X days = DAYSTO1983;
- X for (i = 1983; i < year; i++)
- X days += 365 + leapyear(i);
- X for (i = 0; i < month; i++)
- X days += daysinmonth[i] + (i == 1 ? leapyear(year) : 0);
- X days += day - 1; /* days since 1 Jan 1970 */
- X if (setdayofweek)
- X days += dayofweek;
- X return days * SECINDAY + hour * SECINHOUR + minute * SECINMIN + second;
- X}
- X
- X
- Xstatic
- Xadjust()
- X{
- X register int dim;
- X
- X /*
- X * make sure time defaults to the future
- X */
- X if (setdayofweek || setyear || month > tim->tm_mon)
- X return;
- X if (month < tim->tm_mon) {
- X year++;
- X return;
- X }
- X /*
- X * month == tim->tm_mon
- X */
- X if (day > tim->tm_mday)
- X return;
- X if (day < tim->tm_mday) {
- X if (setmonth || ++month / 12)
- X year++, month %= 12;
- X return;
- X }
- X /*
- X * month == tim->tm_mon && day == tim->tm_mday
- X */
- X if ((long)(hour*SECINHOUR + minute*SECINMIN + second) <
- X (long)(tim->tm_hour*SECINHOUR + tim->tm_min*SECINMIN + tim->tm_sec)) {
- X dim = daysinmonth[month] + (month == 1? leapyear(month): 0);
- X if (setday || ++day / dim) {
- X if (setmonth || ++month / 12)
- X year++, month %= 12;
- X day %= dim;
- X }
- X return;
- X }
- X}
- X
- X
- !
- echo 'rna/news.help':
- sed 's/^X//' >'rna/news.help' <<'!'
- XCommands to read news:
- X
- XRETURN either print current article or go to next article and print header
- X
- X. print current article + or n go to next article
- X- go to previous article s [file] save current article
- Xh print current header H print current header in full
- Xu unsubscribe from followups U unsubscribe from current group
- Xq or EOT quit x exit (as if no articles seen)
- X<number> go to article <number> !cmd shell escape
- XN [newsgrp] go to next newsgroup DEL break to command level
- X
- XCommands to post/reply/cancel news:
- X
- Xc cancel article r reply to sender (by mail)
- Xf post a followup article p post new article
- Xm person mail to person
- X
- XCommands when posting/replying (p, r, f and m commands):
- X
- X. or EOT terminate article .e edit article
- X.!cmd shell escape .i interpolate current item
- XDEL abort posting/mailing
- !
- echo 'rna/newsrc.c':
- sed 's/^X//' >'rna/newsrc.c' <<'!'
- X/*
- X * newsrc file handling
- X */
- X
- X#include "defs.h"
- X
- Xstatic char nrcname[] = NEWSRC;
- X
- Xstatic char *rcname; /* full pathname of .newsrc */
- Xnewsrc *rc; /* internal .newsrc */
- Xchar *rcgrps; /* subscription from .newsrc */
- Xstatic newsrc *lastrc; /* last newsrc struct in list */
- Xstatic int rclineno; /* current lineno in .newsrc */
- Xstatic bool sortrc; /* if we should sort on output */
- X
- Xstatic newsrc *findnewsrc();
- X
- Xreadnewsrc()
- X{
- X register FILE *f;
- X static char option[] = "options";
- X char word[BUFSIZ], rest[BUFSIZ];
- X extern char *getenv();
- X
- X if ((rcname = getenv("HOME")) == NULL)
- X error("No $HOME in environment.");
- X rcname = newstr3(rcname, "/", nrcname);
- X if ((f = fopen(rcname, "r")) == NULL)
- X return;
- X
- X rclineno = 0;
- X while (getline(f, word, rest))
- X if (CMP(word, option) == 0)
- X dooptions(rest);
- X else
- X dorcline(word, rest);
- X (void) fclose(f);
- X}
- X
- X/*
- X * Read a line from f, put first word into w and the rest into r.
- X * Discard trailing newline instead of storing it.
- X * This is a poor design, as w & r are unchecked for overrun.
- X */
- Xstatic
- Xgetline(f, w, r)
- Xregister FILE *f;
- Xchar *w, *r;
- X{
- X register int c;
- X register char *s;
- X
- X rclineno++;
- X s = w;
- X while ((c = getc(f)) != EOF && c != ' ' && c != '\t')
- X *s++ = c; /* stash first word */
- X *s = '\0';
- X
- X if (c != EOF) {
- X s = r;
- X while ((c = getc(f)) != EOF && c != '\n')
- X *s++ = c; /* stash the rest */
- X *s = '\0';
- X }
- X
- X if (c != '\n' && c != EOF)
- X error("Bad format: %s line %d: %s", rcname, rclineno, w);
- X
- X return c != EOF;
- X}
- X
- X/*
- X * Parse s into words and simulate command line arguments with them.
- X */
- Xstatic
- Xdooptions(s)
- Xchar *s;
- X{
- X register char *cp;
- X register int argc;
- X register char **argv;
- X
- X cp = s;
- X while (isspace(*cp))
- X cp++;
- X if (!*cp)
- X return;
- X
- X argc = 1;
- X argv = (char **) myalloc(sizeof(char *));
- X argv[argc - 1] = cp;
- X while (*cp && (cp = strpbrk(cp, " \t")) != NULL) {
- X while (*cp == ' ' || *cp == '\t')
- X *cp++ = '\0';
- X if (*cp) {
- X argc++;
- X argv = (char **) myrealloc((char *) argv,
- X argc * (int)sizeof(char *));
- X argv[argc - 1] = cp;
- X }
- X }
- X if (options(argc, argv, false))
- X error("Bad options: %s line %d: %s", rcname, rclineno, s);
- X free((char *) argv);
- X}
- X
- X/*
- X * Parse w & r together as a .newsrc newsgroup line.
- X */
- Xstatic
- Xdorcline(w, r)
- Xchar *w, *r;
- X{
- X register char lastw;
- X register int len;
- X register newsrc *np;
- X
- X len = strlen(w);
- X lastw = w[len - 1]; /* save presumed colon or bang */
- X w[len - 1] = '\0'; /* nuke presumed colon */
- X while (*r == ' ' || *r == '\t')
- X r++; /* skip extra whitespace */
- X
- X /* kludges, hacks, etc. for compatibility with other readers */
- X if (strncmp(r, "1-", sizeof "1-"-1) == 0)
- X r += sizeof "1-"-1; /* skip usual `1-' */
- X if (*r == '\0') /* rn's: `news.trash: ' */
- X r = "0"; /* fake a zero */
- X
- X if (lastw != ':' && lastw != NEGCHAR || !isdigit(*r))
- X error("Bad line: %s line %d: %s", rcname, rclineno, w);
- X
- X np = NEW(newsrc);
- X np->n_subscribe = (bool) (lastw == ':'); /* colon or bang? */
- X np->n_next = NIL(newsrc);
- X np->n_last = atoi(r); /* stash first number only */
- X np->n_name = newstr(w); /* stash n.g. name */
- X
- X if (rc == 0)
- X rc = np;
- X else
- X lastrc->n_next = np;
- X lastrc = np;
- X}
- X
- X/*
- X * for every group in active list, which belongs to the specified subscription
- X * list, and has messages to be read, call func
- X * if no mention in newsrc file, make new entry
- X */
- Xapply(alist, group, func, dolast)
- Xactive *alist;
- Xchar *group;
- Xapplycom (*func)();
- Xbool dolast;
- X{
- X register active *ap;
- X register newsrc *np;
- X register applycom act;
- X register bool donesome;
- X
- X donesome = false;
- X do {
- X act = stop;
- X for (ap = alist; ap; ap = ap->a_next) {
- X if (ap->a_seq == 0 || ap->a_low > ap->a_seq)
- X continue; /* empty group */
- X if (!ngmatch(ap->a_name, group))
- X continue;
- X if ((np = findnewsrc(ap->a_name)) == NIL(newsrc)) {
- X np = NEW(newsrc);
- X np->n_name = newstr(ap->a_name);
- X np->n_next = NIL(newsrc);
- X np->n_last = 0;
- X np->n_subscribe = true;
- X if (!rc)
- X rc = np;
- X else
- X lastrc->n_next = np;
- X lastrc = np;
- X }
- X if (!np->n_subscribe)
- X continue;
- X /*
- X * if we haven't read any news for a while (or at all),
- X * or somehow seq got smaller (active corrupted?),
- X * set last read to oldest available article
- X */
- X if (ap->a_low - 1 > np->n_last || ap->a_seq < np->n_last)
- X np->n_last = ap->a_low - 1;
- X while (np->n_last < ap->a_seq) {
- X donesome = true;
- X switch (act = (*func)(ap, np, false, false)) {
- X case stop:
- X return;
- X case next:
- X continue;
- X case nextgroup:
- X break;
- X case searchgroup:
- X break;
- X }
- X break;
- X } /* while */
- X if (act == searchgroup)
- X break;
- X } /* for */
- X if (act != searchgroup && dolast && donesome)
- X act = (*func)(NIL(active), NIL(newsrc), true, false);
- X } while (act == searchgroup);
- X}
- X
- X/*
- X * find if a newrc entry exists,
- X * taking advantange of the fact that requests should be
- X * in the same order
- X *
- X * detect when the newsrc gets out of order
- X * so it can be sorted at the end of the session
- X */
- Xstatic newsrc *
- Xfindnewsrc(name)
- Xregister char *name;
- X{
- X register newsrc *np, *start;
- X register bool found;
- X static newsrc *nextp;
- X
- X if (!rc)
- X return NIL(newsrc);
- X
- X found = false;
- X np = nextp ? nextp : rc;
- X nextp = start = np;
- X do {
- X if (CMP(np->n_name, name) == 0) {
- X found = true;
- X break;
- X }
- X np = np->n_next;
- X if (!np)
- X np = rc;
- X } while (np != nextp);
- X
- X if (!found)
- X return NIL(newsrc);
- X nextp = np->n_next;
- X if (np != start)
- X sortrc = true;
- X return np;
- X}
- X
- X/*
- X * rewrite the newsrc file
- X */
- Xwritenewsrc(alist)
- Xactive *alist;
- X{
- X register FILE *f;
- X register active *ap;
- X register newsrc *np;
- X register int i;
- X extern char **uflag;
- X extern int usize;
- X
- X if (!rc && !uflag && (!rcgrps || !*rcgrps))
- X return;
- X
- X signal(SIGINT, SIG_IGN);
- X signal(SIGQUIT, SIG_IGN);
- X
- X f = fopenf(rcname, "w");
- X if (rcgrps && *rcgrps)
- X (void) fprintf(f, "options -n %s\n", rcgrps);
- X if (uflag) {
- X scanhist(uflag, usize); /* forget id's not in history */
- X for (i = 0; i < usize; i++) /* print whats left */
- X if (uflag[i])
- X (void) fprintf(f, "options -u %s\n", uflag[i]);
- X }
- X if (sortrc) {
- X /*
- X * sort newsrc so next time we use it,
- X * history/newsrc comparisons will be faster
- X */
- X for (ap = alist; ap; ap = ap->a_next)
- X if (np = findnewsrc(ap->a_name))
- X writengline(f, np);
- X } else
- X for (np = rc; np; np = np->n_next)
- X writengline(f, np);
- X (void) fclose(f);
- X}
- X
- Xstatic
- Xwritengline(f, np) /* write .newsrc n.g. line in normal form on f */
- Xregister newsrc *np;
- X{
- X (void) fprintf(f, "%s%c 1-%d\n", np->n_name,
- X (np->n_subscribe? ':': NEGCHAR), np->n_last);
- X}
- !
- echo 'rna/readnews.1':
- sed 's/^X//' >'rna/readnews.1' <<'!'
- X.TH READNEWS 1
- X.SH NAME
- Xnews, readnews \- read news articles
- X.SH SYNOPSIS
- X.B readnews
- X.RB [ -n
- Xnewsgroups]
- X.RB [ -i ]
- X.RB [ -clpC ]
- X.RB [ -s [ -+?
- X.RI [ group ]]]
- X.RB [ -u
- Xmessageid]
- X.SH DESCRIPTION
- X.I Readnews
- Xwithout arguments enters command mode,
- Xwhich allows printing of unread articles.
- XThis is the normal way of using
- X.IR readnews .
- X.P
- X.I Readnews
- Xmaintains a
- X.I .newsrc
- Xfile in the user's home directory that specifies
- Xall news articles already read.
- XIt is updated at the end of each reading session.
- X.P
- XSome useful functions are available which don't use command mode.
- XThe flags for these are:
- X.TP
- X.B -c
- XCheck if there is news, and if so print `You have news.'.
- XA line `readnews -c' is usually placed in the system
- X.I .profile
- X.RB ( /etc/profile ).
- X.TP
- X.B -C
- XCheck if there is news, and print the groups and number of
- Xarticles in each group to be read.
- X.TP
- X.B -l
- XList the titles of available news articles.
- X.TP
- X.B -p
- XPrint all articles on standard output,
- Xand update
- X.IR newsrc .
- X.TP
- X.B -s
- XPrint the newsgroup subscription list.
- X.TP
- X.BI -s+ " group"
- XAdd
- X.I group
- Xto the subscription list.
- X.TP
- X.BI -s- " group"
- XSubtract
- X.I group
- Xfrom the subscription list.
- X.TP
- X.B -s?
- XList currently active newsgroups.
- X.P
- XThe remaining flags determine article selection,
- Xand may also appear in the
- X.I .newsrc
- Xfile.
- XOptions may be specified in the
- X.I .newsrc
- Xfile by entering lines prefixed with the word `options',
- Xfollowed by the options arguments.
- XThis is most useful with the
- X.B -n
- Xflag, specifying the usual groups one wishes to subscribe to.
- X.TP
- X\fB-n \fInewsgroups\fR
- XSelect all articles belonging to
- X.IR newsgroups .
- X.I newsgroups
- Xis a comma separated list of newsgroup names.
- XThe character `!' may be used to exclude certain groups,
- Xand the word `all' can be used to match any group.
- Xe.g. `-n all,!net.jokes'
- X.TP
- X.B -i
- XIgnore
- X.I .newsrc
- Xfile. It is not read or updated.
- XThis allows selection of articles that have already been read.
- X.TP
- X\fB-u \fImessageid\fR
- XUnsubscribe to followup articles referring to
- X.IR messageid .
- X(This flag is usually only placed in the
- X.I .newsrc
- Xfile as a result of the `u' command.)
- X.SH COMMANDS
- XThis section details the commands available when
- X.I readnews
- Xis in command mode (no
- X.B -clpsC
- Xarguments).
- XThe simplest way of using this mode, is to enter RETURN after every
- Xprompt.
- XThis will present to the user, a short heading for an article, then a prompt.
- XTyping RETURN again will print the article body.
- XTyping RETURN yet again will print the next heading, and so on.
- XIf having read the heading, you don't wish to read the article, you may
- Xtype `n' (or `+' or ';') which will take you directly to the next heading.
- X.P
- X.P
- XAn article is treated as having been read, if either you have seen
- Xthe article body, or typed `n' to skip over it.
- X.P
- XA number of commands operate on the `current' article.
- XThis is defined as the article whose header you have most recently seen.
- X.P
- XThe commands to read news are:
- X.TP
- X.B RETURN
- XEither print the current article,
- Xor go to the next article and print its header.
- X.TP
- X\fBn\fR or \fB+\fR or \fB;\fR
- XGo to the next article and print its header.
- X.TP
- X.B .
- XPrint the current article.
- X.TP
- X.B -
- XGo back to the previous article. This is a toggle, typing it
- Xtwice returns you to the original article.
- X.TP
- X.I number
- XGo to the article
- X.I number
- Xin the current newsgroup.
- XLike the `-' command,
- Xyou always return to the original article
- Xafter reading the selected article.
- X.TP
- X\fBs \fR[\fIfile\fR]
- XSave the current article, either in the specified file, or
- Xin
- X.BR $HOME/articles .
- X.TP
- X.B h
- XPrint the current header (slightly more verbose than normal header).
- X.TP
- X.B H
- XPrint the current header in full (very verbose).
- X.TP
- X\fBN \fR[\fInewsgroup\fR]
- XGo to the next newsgroup, or to the specified newsgroup.
- X.TP
- X.B u
- XUnsubscribe from all further followup articles on this topic.
- X.TP
- X.B U
- XUnsubscribe from this newsgroup, and go to the next newsgroup.
- X.TP
- X\fB!\fIcommand\fB
- XShell escape.
- X.I Command
- Xis executed.
- XIf
- X.I command
- Xis `!'
- Xthe last escape command is executed.
- X.TP
- X\fBq\fR or \fBEOT\fR
- XQuit.
- XThe
- X.I .newsrc
- Xfile will be updated provided the flag
- X.B -i
- Xwas not specified.
- X.TP
- X.B x
- XExit.
- X.I .newsrc
- Xis left unchanged (as if no articles had been read).
- X.TP
- X.B DEL
- XAn interrupt will cause
- X.I readnews
- Xto terminate its current activity and return to command mode.
- XAn interrupt in command mode will cause `Interrupt' to be printed,
- Xand a subsequent interrupt will cause immediate exit (as in the `x' command).
- X.P
- XSome commands are available to send/reply or cancel news articles:
- X.TP
- X.B c
- XCancel article. Only the author, or news administrator can do this.
- X.IR postnews (1)
- Xis called to do the actual cancelling.
- X.TP
- X.B r
- XReply to sender of the current article by mail.
- X.I Readnews
- Xsets up the appropriate headers, and then calls
- X.IR mail (1)
- Xto send a reply to the sender.
- X.TP
- X.B f
- XPost a followup to the current article.
- X.I Readnews
- Xsets up the appropriate headers, and then calls
- X.IR postnews (1)
- Xto post the followup article.
- X.TP
- X.B p
- XPost an article on a new topic.
- X.IR postnews (1)
- Xis called to post the new article.
- X.TP
- X\fBm \fIperson\fB
- XMail to
- X.IR person .
- X.P
- XWhen replying by mail, or posting an article, the user
- Xis prompted for certain headers, and then the text of the article or mail
- Xitem is entered until a `.' or EOT is entered alone on a line.
- XThen the article/mail is posted/mailed.
- XOther commands are available:
- X.TP
- X\&\fB.e\fR
- XEdit the message/article collected so far (see
- X.IR ed (1)).
- XThe 'To:' or 'cc:' fields may be changed if mailing.
- XAfter editing further lines may be appended to the message.
- X.TP
- X\&\fB.i\fR
- XInterpolate
- Xthe current news article onto the end of the message.
- XThe interpolated item
- Xis indented by four spaces.
- X.TP
- X\&\fB.!\fIcmd\fR or \fB!\fIcmd\fR
- XShell escape.
- X.IR Cmd
- Xis executed.
- X.TP
- X.B DEL
- XCauses posting/mailing to be aborted, and the article entered so far
- Xis saved in
- X.B $HOME/dead.article
- Xor
- X.BR $HOME/dead.letter .
- X.P
- XIn order to permanently resubscribe to a newsgroup denied by `U',
- Xor a series of followups denied by `u' it is necessary to understand
- Xthe format of the
- X.I .newsrc
- Xfile.
- XThe
- X.I .newsrc
- Xfile consists of two types of lines:
- X.TP
- Xoption lines
- XThese start with the word `option' and contain the same arguments
- Xas the
- X.I readnews
- Xcommand on the command line.
- XFollowups are denied with `option -u <messageid>'.
- XTo resubscribe to further followups, the correct options line must be deleted.
- X.TP
- Xread newsgroup lines
- XThese have the format <newsgroup>`:' <number>, where
- X<number> represents the last item number seen in that particular newsgroup.
- XIf the newsgroup has been unsubscribed, the `:' is replaced by a `!'.
- XTo resubscribe the `!' must be changed back to a `:'.
- X.SH FILES
- X.ta 24
- X.nf
- X$HOME/.newsrc options and list of previously read articles
- X%news where the articles are kept
- X/usr/lib/news/active current newsgroups
- X/usr/lib/news/help help file
- X.fi
- X.SH SEE ALSO
- Xpostnews(1), mail(1), ed(1), uusend(8), uurec(8).
- X.SH BUGS
- X.I Readnews
- Xwith the
- X.B -c
- Xflag may say "You have news.", when the available article is a unsubscribed
- Xfollowup article.
- X.P
- XYou may see followups, even if you have used the `u' command.
- XThis is because many sites have faulty news programs, which do
- Xnot follow the correct protocol, or the sender did not use the `r' command.
- X.SH AUTHOR
- XMichael Rourke, University of N.S.W (decvax!mulga!michaelr:elecvax)
- !
- echo done
-
-
-